package com.crois.barrier.web.support;

import com.zhimydou.cloud.auth.core.exception.InvalidClientException;
import com.zhimydou.cloud.auth.core.token.AuthAccessToken;
import com.zhimydou.zlp.constants.TokenConstants;
import com.zhimydou.ztools.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author: HouZeYu
 * @Description:
 * @Date: Created in 14:54 2021/9/28
 */
@Slf4j
public class AuthUtils {
    public static final String CLIENT_ID = "client_id";
    public static final String STATE = "state";
    public static final String SCOPE = "scope";
    public static final String REDIRECT_URI = "redirect_uri";
    public static final String RESPONSE_TYPE = "response_type";
    public static final String USER_OAUTH_APPROVAL = "user_oauth_approval";
    public static final String SCOPE_PREFIX = "scope.";
    public static final String GRANT_TYPE = "grant_type";

    public AuthUtils() {

    }


    private static final String BASIC_ = "Basic ";

    /**
     * 获取requet(head/param)中的token
     * @param request
     * @return
     */
    public static String extractToken(ServerHttpRequest request) {
        String token = extractHeaderToken(request);
        if (token == null) {
            List<String> list = request.getQueryParams().get(TokenConstants.AUTH_HEADER);
            if (CollectionUtil.isNotEmpty(list)){
                token = list.get(0);
            }
            if (token == null) {
                log.debug("Token not found in request parameters.  Not an OAuth2 request.");
            }
        }
        return token;
    }

    /**
     * 解析head中的token
     * @param request
     * @return
     */
    private static String extractHeaderToken(ServerHttpRequest request) {
        List<String> headers = request.getHeaders().get(TokenConstants.AUTH_HEADER);
        if (CollectionUtil.isNotEmpty(headers)){
            String value = headers.get(0);
            if ((value.toLowerCase().startsWith(AuthAccessToken.BEARER_TYPE.toLowerCase()))) {
                String authHeaderValue = value.substring(AuthAccessToken.BEARER_TYPE.length()).trim();
                int commaIndex = authHeaderValue.indexOf(',');
                if (commaIndex > 0) {
                    authHeaderValue = authHeaderValue.substring(0, commaIndex);
                }
                return authHeaderValue;
            }
        }
        return null;
    }

    /**
     * *从header 请求中的clientId:clientSecret
     */
    public static String[] extractClient(ServerHttpRequest request) {
        List<String> headerList = request.getHeaders().get("Authorization");

        if (CollectionUtil.isEmpty(headerList) || !headerList.get(0).startsWith(BASIC_)) {
            throw new InvalidClientException("请求头中client信息为空");
        }
        return extractHeaderClient(headerList.get(0));
    }

    /**
     * 从header 请求中的clientId:clientSecret
     *
     * @param header header中的参数
     */
    public static String[] extractHeaderClient(String header) {
        byte[] base64Client = header.substring(BASIC_.length()).getBytes(StandardCharsets.UTF_8);
        byte[] decoded = Base64.getDecoder().decode(base64Client);
        String clientStr = new String(decoded, StandardCharsets.UTF_8);
        String[] clientArr = clientStr.split(":");
        if (clientArr.length != 2) {
            throw new RuntimeException("Invalid basic authentication token");
        }
        return clientArr;
    }


    public static Set<String> parseParameterList(String values) {
        Set<String> result = new TreeSet();
        if (values != null && values.trim().length() > 0) {
            String[] tokens = values.split("[\\s+]");
            result.addAll(Arrays.asList(tokens));
        }

        return result;
    }

    public static String formatParameterList(Collection<String> value) {
        return value == null ? null : StringUtils.collectionToDelimitedString(value, " ");
    }

    public static Map<String, String> extractMap(String query) {
        Map<String, String> map = new HashMap();
        Properties properties = StringUtils.splitArrayElementsIntoProperties(StringUtils.delimitedListToStringArray(query, "&"), "=");
        if (properties != null) {
            Iterator var3 = properties.keySet().iterator();

            while(var3.hasNext()) {
                Object key = var3.next();
                map.put(key.toString(), properties.get(key).toString());
            }
        }

        return map;
    }

    public static boolean containsAll(Set<String> targetset, Set<String> members) {
        Set<String> target = new HashSet(targetset);
        target.retainAll(members);
        return target.size() == members.size();
    }
}
